package com.reactim.message.controller;

import com.reactim.message.config.management.*;
import com.reactim.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
 * 配置管理控制器
 * 
 * <p>提供配置管理相关的REST API接口，包括配置的动态刷新、
 * 导出导入、差异比较、备份恢复等功能。</p>
 * 
 * <h3>API端点</h3>
 * <ul>
 *   <li><strong>POST /api/config/refresh</strong> - 刷新配置</li>
 *   <li><strong>GET /api/config/export</strong> - 导出配置</li>
 *   <li><strong>POST /api/config/import</strong> - 导入配置</li>
 *   <li><strong>GET /api/config/compare</strong> - 比较配置差异</li>
 *   <li><strong>POST /api/config/backup</strong> - 创建备份</li>
 *   <li><strong>POST /api/config/restore</strong> - 恢复备份</li>
 *   <li><strong>GET /api/config/backups</strong> - 获取备份列表</li>
 * </ul>
 * 
 * @author ReactIM Team
 * @version 1.0.0
 * @since 1.0.0
 */
@RestController
@RequestMapping("/api/config")
@Slf4j
public class ConfigurationManagementController {
    
    @Autowired
    private ConfigurationManagementTool configManagementTool;
    
    /**
     * 刷新配置
     * 
     * <p>动态刷新应用配置，无需重启应用。会在刷新前自动创建备份。</p>
     * 
     * @return 刷新结果
     */
    @PostMapping("/refresh")
    public Result<ConfigurationRefreshResult> refreshConfiguration() {
        try {
            log.info("收到配置刷新请求");
            ConfigurationRefreshResult result = configManagementTool.refreshConfiguration();
            
            if (result.isSuccess()) {
                return Result.success("配置刷新成功", result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("配置刷新失败", e);
            return Result.error("配置刷新失败: " + e.getMessage());
        }
    }
    
    /**
     * 导出配置到文件
     * 
     * @param filePath 导出文件路径
     * @param format 导出格式 (YAML/JSON)
     * @return 导出结果
     */
    @GetMapping("/export")
    public Result<ConfigurationExportResult> exportConfiguration(
            @RequestParam String filePath,
            @RequestParam(defaultValue = "YAML") ConfigurationFormat format) {
        try {
            log.info("收到配置导出请求: {}, 格式: {}", filePath, format);
            ConfigurationExportResult result = configManagementTool.exportConfiguration(filePath, format);
            
            if (result.isSuccess()) {
                return Result.success("配置导出成功", result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("配置导出失败", e);
            return Result.error("配置导出失败: " + e.getMessage());
        }
    }
    
    /**
     * 下载配置文件
     * 
     * @param format 导出格式
     * @return 配置文件内容
     */
    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadConfiguration(
            @RequestParam(defaultValue = "YAML") ConfigurationFormat format) {
        try {
            log.info("收到配置下载请求，格式: {}", format);
            
            // 创建临时文件
            String tempFileName = "reactim-config-" + System.currentTimeMillis() + format.getExtension();
            String tempFilePath = System.getProperty("java.io.tmpdir") + "/" + tempFileName;
            
            // 导出到临时文件
            ConfigurationExportResult result = configManagementTool.exportConfiguration(tempFilePath, format);
            
            if (!result.isSuccess()) {
                return ResponseEntity.badRequest().build();
            }
            
            // 读取文件内容
            Path path = Paths.get(tempFilePath);
            byte[] content = Files.readAllBytes(path);
            
            // 删除临时文件
            Files.deleteIfExists(path);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType(format.getMimeType()));
            headers.setContentDispositionFormData("attachment", tempFileName);
            
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(content);
                    
        } catch (Exception e) {
            log.error("配置下载失败", e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 从文件导入配置
     * 
     * @param file 配置文件
     * @param applyImmediately 是否立即应用
     * @return 导入结果
     */
    @PostMapping("/import")
    public Result<ConfigurationImportResult> importConfiguration(
            @RequestParam("file") MultipartFile file,
            @RequestParam(defaultValue = "false") boolean applyImmediately) {
        try {
            log.info("收到配置导入请求: {}, 立即应用: {}", file.getOriginalFilename(), applyImmediately);
            
            // 保存上传文件到临时位置
            String tempFileName = "imported-config-" + System.currentTimeMillis() + "-" + file.getOriginalFilename();
            String tempFilePath = System.getProperty("java.io.tmpdir") + "/" + tempFileName;
            
            Path tempPath = Paths.get(tempFilePath);
            Files.write(tempPath, file.getBytes());
            
            // 导入配置
            ConfigurationImportResult result = configManagementTool.importConfiguration(tempFilePath, applyImmediately);
            
            // 删除临时文件
            Files.deleteIfExists(tempPath);
            
            if (result.isSuccess()) {
                return Result.success("配置导入成功", result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("配置导入失败", e);
            return Result.error("配置导入失败: " + e.getMessage());
        }
    }
    
    /**
     * 比较配置差异
     * 
     * @param backup1 第一个备份名称
     * @param backup2 第二个备份名称
     * @return 配置差异结果
     */
    @GetMapping("/compare")
    public Result<ConfigurationDiff> compareConfigurations(
            @RequestParam String backup1,
            @RequestParam String backup2) {
        try {
            log.info("收到配置比较请求: {} vs {}", backup1, backup2);
            ConfigurationDiff diff = configManagementTool.compareConfigurations(backup1, backup2);
            return Result.success("配置比较完成", diff);
        } catch (Exception e) {
            log.error("配置比较失败", e);
            return Result.error("配置比较失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建配置备份
     * 
     * @param backupName 备份名称
     * @return 备份结果
     */
    @PostMapping("/backup")
    public Result<ConfigurationBackupResult> createBackup(@RequestParam String backupName) {
        try {
            log.info("收到创建备份请求: {}", backupName);
            ConfigurationBackupResult result = configManagementTool.createBackup(backupName);
            
            if (result.isSuccess()) {
                return Result.success("配置备份创建成功", result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("创建配置备份失败", e);
            return Result.error("创建配置备份失败: " + e.getMessage());
        }
    }
    
    /**
     * 恢复配置备份
     * 
     * @param backupName 备份名称
     * @return 恢复结果
     */
    @PostMapping("/restore")
    public Result<ConfigurationRestoreResult> restoreBackup(@RequestParam String backupName) {
        try {
            log.info("收到恢复备份请求: {}", backupName);
            ConfigurationRestoreResult result = configManagementTool.restoreBackup(backupName);
            
            if (result.isSuccess()) {
                return Result.success("配置备份恢复成功", result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("恢复配置备份失败", e);
            return Result.error("恢复配置备份失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取备份列表
     * 
     * @return 备份列表
     */
    @GetMapping("/backups")
    public Result<List<ConfigurationBackupInfo>> listBackups() {
        try {
            log.info("收到获取备份列表请求");
            List<ConfigurationBackupInfo> backups = configManagementTool.listBackups();
            return Result.success("获取备份列表成功", backups);
        } catch (Exception e) {
            log.error("获取备份列表失败", e);
            return Result.error("获取备份列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除配置备份
     * 
     * @param backupName 备份名称
     * @return 删除结果
     */
    @DeleteMapping("/backup/{backupName}")
    public Result<Boolean> deleteBackup(@PathVariable String backupName) {
        try {
            log.info("收到删除备份请求: {}", backupName);
            boolean success = configManagementTool.deleteBackup(backupName);
            
            if (success) {
                return Result.success("配置备份删除成功", true);
            } else {
                return Result.error("配置备份不存在或删除失败");
            }
        } catch (Exception e) {
            log.error("删除配置备份失败", e);
            return Result.error("删除配置备份失败: " + e.getMessage());
        }
    }
}